今天要介紹的是在 Line Bot 加入圖文選單,那什麼是圖文選單呢?
下方紅框的部分就是圖文選單。
圖文選單的主要用途如下:
要建立圖文選單有兩種方式,第一種進入 Line@ 後台有功能可以使用,第二種透過 Postman 等軟體或寫程式呼叫 API。
雖然下面要介紹的是 API,不過不是因為 "身為工程師當然是要寫程式" 這個原因,我其實很想用功能,沒用的原因是我以為後台建立圖文選單的功能需要收費,小弟口袋不深只好選擇 API,不過最近查資料發現此功能已經變成免費的,可以安心服用了。
2019/4/18 後只要升級官方帳號 2.0 就可以免費使用
既然功能都免費了,當然要用好用滿,不過這篇還是以介紹 API 為主,後台編輯功能可以參考這篇文章,連結: 【功能介紹】圖文影音內容 - 圖文選單 - 電腦版
建立 Line Bot 圖文選單需要 Line Bot 的 channel access token
,還沒有建立 Line Bot 的讀者可以參考第一篇 [Day01] LINE Bot 帳號申請
這裡會使用 Postman 呼叫 API,Postman 網址。
建立圖文選單有三個步驟:
1. 建立圖文選單
POST https://api.line.me/v2/bot/richmenu
Request headers
Authorization: Bearer {channel access token}
Content-Type: application/json
Request body
{
"size": {
"width": 2500,
"height": 843
},
"selected": false,
"name": "richmenu-1",
"chatBarText": "選單1",
"areas": [
{
"bounds": {
"x": 0,
"y": 0,
"width": 833,
"height": 843
},
"action": {
"type": "message",
"label": "文字",
"text": "Hello, iBot!"
}
},
{
"bounds": {
"x": 833,
"y": 0,
"width": 833,
"height": 843
},
"action": {
"type": "uri",
"label": "網址",
"uri": "https://ithelp.ithome.com.tw/users/20106865/ironman/2732"
}
},
{
"bounds": {
"x": 1666,
"y": 0,
"width": 833,
"height": 843
},
"action": {
"type": "postback",
"label": "選單2",
"data": "action=changeMenu2"
}
}
]
}
Response
{
"richMenuId": "{rich menu id}"
}
這裡稍微解釋一下 API 的用法,詳細說明可以參考官方文件
第一個區塊是 API 的網址,需要使用 POST
方法呼叫
第二區塊是 header 的參數,{channel access token}
要替換成自己申請 Line Bot 時的那個 token,application/json
表示下方 Request body 的格式為 json
第三區塊為 http 的主體,用來定義圖文選單相關的設定
size: 圖文選單圖片的長寬,必需為以下尺寸:
2500x1686
、2500x843
、1200x810
、1200x405
、800x540
、800x270
selected: 選單是否預設開啟,這裡我設定為 false,預設不開啟。
name: 選單名稱,用於識別和管理選單,不會顯示給使用者。
chatBarText: 顯示在聊天視窗下方的選單文字。
areas: 用於定義按鈕的可點墼區域。
bounds 用於定義座標和大小
x、y: 起始座標
width: 寬度
height: 高度
action 用於定義觸發的動作
type: 動作類型,詳細說明可以參考 官方文件
label: 動作標籤,用於客戶端輔助功能
text: 發送到聊天視窗的文字
data: 透過 webhook 回傳到後端的字串
第四區塊為回傳訊息,選單建立成功後會回傳 {rich menu id}
後面 API 會使用到。
Postman 結果
2. 上傳圖文選單的圖片
POST https://api.line.me/v2/bot/richmenu/{rich menu id}/content
[Request headers]
-----------------
Authorization: Bearer {channel access token}
Content-Type: image/jpeg or image/png
Content-Length: request body 大小 (byte)
[Request body]
--------------
圖片主體
格式: JPEG 或 PNG
長寬: 2500x1686, 2500x843, 1200x810, 1200x405, 800x540, 800x270
大小限制: 1 MB
[Response]
----------
{}
將第一步得到的 {rich menu id}
帶入網址,接著 Body 部分選擇 binary
可以選擇圖片,最後按送出,這個步驟比較簡單,成功會回傳 JSON 空物件。
Postman 結果
Content-Length 好像可以省略,怕算錯乾脆不要了 (╯‵□′)╯︵┻━┻
3. 設定預設的圖文選單
POST https://api.line.me/v2/bot/user/all/richmenu/{rich menu id}
[Request headers]
Authorization: Bearer {channel access token}
[Request body]
無
[Response]
{}
這步驟會設定所有用戶預設看到的圖文選單,還有另一個 API 可以單獨設定某位用戶的選單,後面介紹動態選單的時候會用到。
Postman 結果
。:.゚ヽ(*´∀`)ノ゚.:。
因為對 Photoshop 不熟,這裡我用 HTML + Font Awesome 把樣子排出來,再用 JS 套件將 HTML 轉成圖片,用於製作陽春的選單還蠻方便的。
HTML
<table>
<tr>
<td id="block1">
<i class="fa fa-file-text-o icon"></i>
<div class="text">文字</div>
</td>
<td id="block2">
<i class="fa fa-link icon"></i>
<div class="text">網址</div>
</td>
<td id="block3">
<i class="fa fa-list icon"></i>
<div class="text">選單</div>
</td>
</tr>
</table>
<div style="margin-top: 10px">
<input type="button" id="btn" value="另存圖片"/>
</div>
<div id="img"></div>
CSS
table {
width: 2500px;
height: 843px;
border-collapse: collapse;
font-family: Microsoft JhengHei;
}
table td {
text-align: center;
padding: 0px;
}
.icon {
color: #ffffff;
font-size: 280px;
}
.text {
margin-top: 10px;
color: #ffffff;
font-size: 120px;
font-weight: bold;
}
#block1 {
background-color: #00D084;
width: 33.33%;
}
#block2 {
background-color: #2D8665;
width: 33.33%;
}
#block3 {
background-color: #00D084;
width: 33.33%;
}
JS
$(function() {
$("#btn").click(function() {
html2canvas($("table"), {
onrendered: function(canvas) {
$("#img").append(canvas);
$('#img canvas').css('max-width', '600px');
}
});
});
});
色碼
官方也有許多不錯的資源供大家下載,可以進去挖寶。
https://events.line.me/tw/lineat/minisite/wp-content/themes/line/download.php
最後要介紹的是動態選單,什麼是動態選單?
這裡的動態是指,利用 設定的個別用戶選單
這個 API,讓 Line Bot 可以個別切換某位使用者的選單,用途如下。
接下來會實作一個兩層的選單,使用者可以透過上下頁按紐切換。
切換邏輯會利用 API 的優先順序特性,例如: 按下一頁時,程式會將 個別用戶選單
設定為 選單2
,因為 個別優先於預設
選單就會切換,而按上一頁時,程式將 個別用戶選單
移除,選單就會切換回去,這裡也可以不用移除,將 個別用戶選單
設定為 選單1
也可以。
圖文選單顯示的優先順序(高到低):
照上面介紹的方法製作兩個選單。
選單1
"action": {
"type": "postback",
"label": "下一頁",
"data": "action=next"
}
選單2
"action": {
"type": "postback",
"label": "上一頁",
"data": "action=prev"
}
可以看到按鈕的 action 我使用了 postback 類型,這個類型會在使用者點擊按紐時,透過 Webhook 呼叫後端的程式,且不會有文字出現在聊天視窗上
。
另外還可以使用像 QueryString 一樣的方式附帶參數,例如上方我使用 next 和 prev 分別代表兩個按鈕動作,後端收到後就可以以此去執行各自的程式。
不過電腦版的 LINE 看不到圖文選單
,這時就只能用文字控制 line Bot 功能,因此各有其優缺點,但如果單看圖文選單,比起文字類型會更推薦使用 Postback。
開啟 LineBotApp.cs 加入下面程式。
protected override async Task OnPostbackAsync(PostbackEvent ev)
{
var query = HttpUtility.ParseQueryString(ev.Postback.Data);
//頻道Id
var channelId = ev.Source.Id;
//使用者Id
var userId = ev.Source.UserId;
switch (query["action"])
{
//下一頁
case "next":
{
//設定個別用戶選單
await _messagingClient.LinkRichMenuToUserAsync(userId, "選單2 的Id");
}
break;
//上一頁
case "prev":
{
//移除個別用戶選單
await _messagingClient.UnLinkRichMenuFromUserAsync(userId);
}
break;
}
}
完整 LineBotApp.cs 可以參考:
[Day02] 使用 .NET Core 3.0 + LineMessagingApi 串接 Line Bot
預設選單
點下一頁會跳到選單2,點上一頁又會返回
這邊是筆記,將上面使用 Postman 的地方改成 C#。
var richMenu = new RichMenu()
{
Size = new ImagemapSize(2500, 843),
Selected = false,
Name = "richmenu-1",
ChatBarText = "選單1",
Areas = new List<ActionArea>()
{
new ActionArea()
{
Bounds = new ImagemapArea(0, 0 ,833, 843),
Action = new MessageTemplateAction("文字", "Hello, iBot!")
},
new ActionArea()
{
Bounds = new ImagemapArea(833, 0 ,833, 843),
Action = new UriTemplateAction("網址", "https://ithelp.ithome.com.tw/users/20106865/ironman/2732")
},
new ActionArea()
{
Bounds = new ImagemapArea(1666, 0 ,833, 843),
Action = new PostbackTemplateAction("選單2", "action=changeMenu2")
}
}
};
var richMenuId = await _messagingClient.CreateRichMenuAsyn(richMenu);
var image = new MemoryStream(File.ReadAllBytes(@"richmenu.png"));
await _messagingClient.UploadRichMenuPngImageAsync(image, richMenuId);
await _messagingClient.SetDefaultRichMenuAsync(richMenuId);
詳細內容可參考 官方文件
GET https://api.line.me/v2/bot/richmenu/list
[Request headers]
Authorization: Bearer {channel access token}
[Response]
JSON 格式的列表清單
DELETE https://api.line.me/v2/bot/richmenu/{rich menu id}
[Request headers]
Authorization: Bearer {channel access token}
[Response]
{}
GET https://api.line.me/v2/bot/user/all/richmenu
[Request headers]
Authorization: Bearer {channel access token}
[Response]
{
"richMenuId": "{rich menu id}"
}
DELETE https://api.line.me/v2/bot/user/all/richmenu
[Request headers]
Authorization: Bearer {channel access token}
[Response]
{}
這篇本來沒準備寫這麼長,沒想到資料越找越多,還意外發現動態選單的用法,手癢就自己實做了一次。最後的切換選單功能,用起來其實有點卡卡的,會延遲個1~2秒,在可以接受的範圍拉,選單功能如果不需要頻繁切換,總體來說還是不錯的。
在過程中還看到一位大大的鐵人文 LINE bot 好好玩 30 天玩轉 LINE API
這位大大把 LINE 可以玩的 API 都試過了一次,我這才知道原來 LINE API 可以玩的東西這麼多,LINE 真是越來越強大了,有興趣的朋友可以去看他的鐵人文。
下一篇要將 Line Bot 結合資料庫,內容會介紹如何在 Azure 的 App Service 開啟 MySql 資料庫,並且會搭配 Entity Framework 使用,會教大家建立 Model 並透過 Fluent API 設定資料表的屬性和關聯。
最後會實做出一個完整的功能,目前規劃是可以透過 Line Bot 訂閱某人 it 邦的首頁,程式會透過爬蟲每天去取得文章的觀看數,接著可以透過 Line Bot 查詢每日、每周、每月,前5名,點閱數增加最多的文章。
今天就到這,感謝大家觀看~~~
用LINE bot api建立line@圖文選單
如何建立LineBot圖文選單
Linebot-Demo-DynamicRichMenu
Messaging API reference
Using rich menus
請問可以做postman製作子選單的詳細教學嗎?遇到瓶頸了看不懂
首先使用文中介紹的方式建立兩個圖文選單
接著將第一個選單設為預設選單
POST https://api.line.me/v2/bot/user/all/richmenu/{richMenuId_1}
[Request headers]
Authorization: Bearer {channel access token}
[Response]
{}
然後就可以使用下面的 API 切換選單
下一頁:
設定 User 的 Rich Menu
POST
https://api.line.me/v2/bot/user/{userId}/richmenu/{richMenuId_2}
[Request headers]
Authorization: Bearer {channel access token}
[Response]
{}
上一頁:
取消 User 的 Rich Menu
DELETE https://api.line.me/v2/bot/user/{userId}/richmenu
[Request headers]
Authorization: Bearer {channel access token}
[Response]
{}
這個是不是不能用python呀?
user id是line developers裡面的user id嗎?
我製作好2個選單,下一頁跟上一頁也都弄好了
但我不是很明白 "然後就可以使用下面的 API 切換選單"這一句
不好意思我第一次學習,很多地方不懂
Python 我使用這個 SDK。
https://github.com/line/line-bot-sdk-python
@handler.add(PostbackEvent)
def handle_postback(event):
# postback 資料
data = event.postback.data
# 使用者Id
userId = event.source.user_id
# 下一頁
if data == "action=next":
# 設定個別用戶選單
line_bot_api.link_rich_menu_to_user(userId, <rich_menu_id>)
# 上一頁
elif data == "action=prev":
# 移除個別用戶選單
line_bot_api.unlink_rich_menu_from_user(userId)
1.user id是line developers裡面的user id嗎?
不是喔,是 Message API 傳給我們的使用者Id
2.但我不是很明白 "然後就可以使用下面的 API 切換選單"這一句
下面兩個 API 可以讓不同使用者看到不同的選單
切換選單就是運用這兩個 API 達成的
不過一般不會直接拿來使用
會向上面的程式一樣
使用官方包裝好的 SDK
所以我是要在我的程式碼加上上面那一段嗎?
然後postman不用更動的意思嗎?
那上面的程式碼哪些是我要改的呀
恩恩,Postman 只要做 建立選單 和 設定預設選單 就好
子選單切換需要用程式
那上面的程式碼哪些是我要改的呀
不知道你目前的寫法,無法給建議
所以上一頁跟下一頁那個也做出來就好不用動對嗎?
目前只有最基本的東西,將程式與linebot做結合而已
將上面的程式直接加入 callback 下方就可以<rich_menu_id>
的部分替換成第二選單的 id
不過我沒有測過,你要試試看
加進去了,但還是沒反應,不知道為什麼...
user id 是這邊個嗎
可以了,感謝你
用程式取得的 userId 才能符合所有使用者喔
# 使用者Id
userId = event.source.user_id
博主您好,想請問我的postman設定是不是有問題?,一直報cors error的錯orz
網頁版的 Postman 有跨域限制 (這是瀏覽器本身的安全機制)
可以改用桌面板或 Chrome 擴充版
謝謝你的教學,我成功了✧*。٩(ˊᗜˋ*)و✧*
想請問,我的line bot後端是架在heroku,若我想做出動態圖文選單,那麼LineBotApp.cs要怎麼加上去執行呢?
原程式是 Python 的話,感覺改成 Python 比較快 ?
SDK:
https://github.com/line/line-bot-sdk-python
@handler.add(PostbackEvent)
def handle_postback(event):
# postback 資料
data = event.postback.data
# 使用者Id
userId = event.source.user_id
# 下一頁
if data == "action=next":
# 設定個別用戶選單
line_bot_api.link_rich_menu_to_user(userId, <rich_menu_id>)
# 上一頁
elif data == "action=prev":
# 移除個別用戶選單
line_bot_api.unlink_rich_menu_from_user(userId)
哇!太感謝啦
有成功了,在改改圖片就好,真的非常謝謝您